<template>
  <div class="room-map-layout">
    <!-- 左侧可伸缩侧边栏 -->
    <div class="sidebar" :class="{ 'collapsed': sidebarCollapsed }">
      <!-- 侧边栏头部 -->
      <div class="sidebar-header">
        <h3 v-if="!sidebarCollapsed" class="sidebar-title">房间地图控制</h3>
        <el-button 
          :icon="sidebarCollapsed ? 'ArrowRight' : 'ArrowLeft'"
          @click="toggleSidebar"
          size="small"
          circle
          class="collapse-btn"
        />
      </div>
      
      <!-- 控制面板 -->
      <div class="controls" v-if="!sidebarCollapsed">
        <el-form :model="formData" label-position="top" @submit.prevent="loadRoomData">
          <el-form-item label="房间名称:">
            <el-input 
              v-model="roomName" 
              placeholder="例如: W1N1"
            />
          </el-form-item>
          <el-form-item label="分片:">
            <el-input 
              v-model="shardName" 
              placeholder="例如: shard3"
            />
          </el-form-item>
          <el-form-item label="代理模式:">
            <el-switch 
              v-model="useViteProxy" 
              active-text="Vite代理"
              inactive-text="CORS代理"
            />
          </el-form-item>
          <el-form-item>
            <el-button 
              type="primary" 
              @click="loadRoomData" 
              :loading="loading"
              style="width: 100%"
            >
              加载地图
            </el-button>
          </el-form-item>
        </el-form>
        
        <!-- 地图控制 -->
        <div class="map-controls" v-if="terrainData.length > 0">
          <el-divider content-position="left">地图控制</el-divider>
          <el-form-item label="缩放比例:">
            <el-slider 
              v-model="mapScale" 
              :min="0.2" 
              :max="3" 
              :step="0.1"
              show-input
              :show-input-controls="false"
            />
          </el-form-item>
          <el-form-item>
            <el-button @click="resetMapScale" size="small" style="width: 100%">
              重置缩放
            </el-button>
          </el-form-item>
        </div>
      </div>
      
      <!-- 错误信息 -->
      <div class="error-message" v-if="errorMessage && !sidebarCollapsed">
        <el-alert :title="errorMessage" type="error" show-icon />
      </div>
    </div>
    
    <!-- 右侧地图区域 -->
    <div class="map-area">
      <div class="map-container" v-if="terrainData.length > 0">
        <div 
          class="map-viewport" 
          @wheel="handleMapWheel"
          @mousedown="handleMapMouseDown"
          @mousemove="handleMapMouseMove"
          @mouseup="handleMapMouseUp"
          @mouseleave="handleMapMouseUp"
        >
          <canvas 
            ref="mapCanvas" 
            :width="canvasSize" 
            :height="canvasSize"
            class="room-map"
            :style="{ 
              transform: `scale(${mapScale}) translate(${mapOffset.x}px, ${mapOffset.y}px)`,
              cursor: isDragging ? 'grabbing' : 'grab'
            }"
          ></canvas>
        </div>
      </div>
      
      <!-- 地图为空时的占位 -->
      <div class="map-placeholder" v-else>
        <el-empty 
          description="请在左侧输入房间信息并加载地图"
          :image-size="200"
        />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick, computed } from 'vue'

const roomName = ref('W1N1')
const shardName = ref('shard3')
const loading = ref(false)
const errorMessage = ref('')
const terrainData = ref<number[]>([])
const objectsData = ref<any[]>([])
const mapCanvas = ref<HTMLCanvasElement | null>(null)
const useViteProxy = ref(true)  // 默认使用 Vite 代理

// 侧边栏状态
const sidebarCollapsed = ref(false)

// 地图缩放和拖拽状态
const mapScale = ref(1)
const mapOffset = ref({ x: 0, y: 0 })
const isDragging = ref(false)
const dragStart = ref({ x: 0, y: 0 })
const dragStartOffset = ref({ x: 0, y: 0 })

// 表单数据 (用于Element Plus form)
const formData = computed(() => ({
  roomName: roomName.value,
  shardName: shardName.value,
  useViteProxy: useViteProxy.value
}))

const canvasSize = 500 // 50x50 网格，每个格子10px

// 地形类型颜色
const terrainColors = {
  0: '#2e2e2e', // 平原 - 浅灰色
  1: '#1b1b1b', // 墙壁 - 深灰色
  2: '#228B22', // 沼泽 - 蓝色'
  3: '#00f4ff', // 墙壁(不可通行) - 绿色
}

// 对象类型颜色
const objectColors = {
  source: '#FFFF00',        // 能量源 - 黄色
  mineral: '#FF00FF',       // 矿物 - 紫色
  controller: '#00FF00',    // 控制器 - 绿色
  spawn: '#FF0000',         // 孵化器 - 红色
  extension: '#FFA500',     // 扩展 - 橙色
  tower: '#800080',         // 炮塔 - 紫色
  storage: '#808080',       // 存储 - 灰色
  terminal: '#00FFFF',      // 终端 - 青色
  lab: '#FFB6C1',          // 实验室 - 浅粉色
  factory: '#A0522D',      // 工厂 - 褐色
  observer: '#4169E1',     // 观察者 - 蓝色
  powerSpawn: '#DC143C',   // 能量孵化器 - 深红色
  extractor: '#8A2BE2',    // 提取器 - 蓝紫色
  link: '#32CD32',         // 链接 - 绿色
  nuker: '#FF1493',        // 核弹发射器 - 深粉色
  road: '#696969',         // 道路 - 暗灰色
  wall: '#2F4F4F',         // 建筑墙 - 深蓝灰色
  rampart: '#006400'       // 城墙 - 深绿色
}

const loadRoomData = async () => {
  if (!roomName.value || !shardName.value) {
    errorMessage.value = '请输入房间名称和分片名称'
    return
  }

  loading.value = true
  errorMessage.value = ''
  
  try {
    // 获取地形数据 - 使用代理，带重试机制
    const terrainEndpoint = `/api/game/room-terrain?room=${roomName.value}&shard=${shardName.value}&encoded=1`
    const terrainResponse = await fetchWithRetry(terrainEndpoint)
    
    if (terrainResponse.error) {
      throw new Error(`API错误: ${terrainResponse.error}`)
    }

    // 解码地形数据
    if (terrainResponse.terrain && terrainResponse.terrain[0] && terrainResponse.terrain[0].terrain) {
      const encodedTerrain = terrainResponse.terrain[0].terrain
      terrainData.value = decodeTerrain(encodedTerrain)
    } else {
      throw new Error('地形数据格式不正确')
    }

    // 获取对象数据 - 使用代理，带重试机制
    try {
      const objectsEndpoint = `/api/game/room-objects?room=${roomName.value}&shard=${shardName.value}&encoded=1`
      const objectsResponse = await fetchWithRetry(objectsEndpoint)
      objectsData.value = objectsResponse.objects || []
    } catch (objError) {
      console.warn('获取对象数据失败，将只显示地形:', objError)
      objectsData.value = []
    }

    // 绘制地图
    await nextTick()
    drawMap()
    
  } catch (error) {
    console.error('加载房间数据失败:', error)
    errorMessage.value = error instanceof Error ? error.message : '加载数据时发生未知错误'
  } finally {
    loading.value = false
  }
}

const fetchWithRetry = async (endpoint: string, maxRetries: number = 3): Promise<any> => {
  let lastError: Error | null = null
  
  for (let i = 0; i < maxRetries; i++) {
    try {
      let url: string
      
      if (useViteProxy.value) {
        // 使用 Vite 代理
        url = endpoint
      } else {
        // 使用公共 CORS 代理
        const screepsUrl = `https://screeps.com${endpoint}`
        url = `https://cors-anywhere.herokuapp.com/${screepsUrl}`
      }
      
      console.log(`尝试请求 ${url} (第 ${i + 1} 次)`)
      
      const headers: Record<string, string> = {
        'Accept': 'application/json',
        'Cache-Control': 'no-cache'
      }
      
      // 如果使用 CORS 代理，添加额外的头部
      if (!useViteProxy.value) {
        headers['X-Requested-With'] = 'XMLHttpRequest'
        headers['Origin'] = window.location.origin
      }
      
      const response = await fetch(url, {
        headers,
        signal: AbortSignal.timeout(15000) // 15秒超时
      })
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
      }
      
      const data = await response.json()
      console.log(`请求成功:`, data)
      return data
      
    } catch (error) {
      lastError = error instanceof Error ? error : new Error(String(error))
      console.warn(`请求失败 (第 ${i + 1} 次):`, lastError.message)
      
      if (i < maxRetries - 1) {
        // 等待一段时间后重试
        await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
      }
    }
  }
  
  throw lastError || new Error('所有重试都失败了')
}

const decodeTerrain = (encoded: string): number[] => {
  const terrain: number[] = []
  
  for (let i = 0; i < encoded.length; i++) {
    const char = encoded[i]
    let value: number
    
    if (char >= '0' && char <= '9') {
      value = parseInt(char)
    } else if (char >= 'a' && char <= 'z') {
      value = char.charCodeAt(0) - 'a'.charCodeAt(0) + 10
    } else if (char >= 'A' && char <= 'Z') {
      value = char.charCodeAt(0) - 'A'.charCodeAt(0) + 36
    } else {
      value = 0
    }
    
    // 每个字符代表一个地形值
    terrain.push(value & 3) // 取最低2位
  }
  
  return terrain
}

const drawMap = () => {
  if (!mapCanvas.value || terrainData.value.length === 0) return
  
  const ctx = mapCanvas.value.getContext('2d')
  if (!ctx) return
  
  const cellSize = canvasSize / 50
  
  // 清空画布
  ctx.clearRect(0, 0, canvasSize, canvasSize)
  
  // 绘制地形
  for (let y = 0; y < 50; y++) {
    for (let x = 0; x < 50; x++) {
      const index = y * 50 + x
      const terrain = terrainData.value[index] || 0
      
      ctx.fillStyle = terrainColors[terrain as keyof typeof terrainColors] || terrainColors[0]
      ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize)
    }
  }
  
  // 绘制对象
  objectsData.value.forEach(obj => {
    if (obj.x !== undefined && obj.y !== undefined) {
      const color = getObjectColor(obj.type)
      if (color) {
        ctx.fillStyle = color
        ctx.fillRect(obj.x * cellSize + 1, obj.y * cellSize + 1, cellSize - 2, cellSize - 2)
      }
    }
  })
}

// 侧边栏控制
const toggleSidebar = () => {
  sidebarCollapsed.value = !sidebarCollapsed.value
}

// 地图缩放控制
const resetMapScale = () => {
  mapScale.value = 1
  mapOffset.value = { x: 0, y: 0 }
}

// 鼠标滚轮缩放
const handleMapWheel = (event: WheelEvent) => {
  event.preventDefault()
  
  const scaleStep = 0.1
  const oldScale = mapScale.value
  
  // 计算新的缩放比例
  let newScale: number
  if (event.deltaY > 0) {
    newScale = Math.max(0.2, mapScale.value - scaleStep)
  } else {
    newScale = Math.min(3, mapScale.value + scaleStep)
  }
  
  // 获取canvas元素的边界矩形
  const canvas = mapCanvas.value
  if (!canvas) return
  
  const canvasRect = canvas.getBoundingClientRect()
  
  // 计算鼠标在canvas中的相对位置（考虑当前的transform）
  const mouseX = event.clientX - canvasRect.left
  const mouseY = event.clientY - canvasRect.top
  
  // 计算canvas中心点
  const canvasCenterX = canvasRect.width / 2
  const canvasCenterY = canvasRect.height / 2
  
  // 计算鼠标相对于canvas中心的位置
  const mouseRelativeX = mouseX - canvasCenterX
  const mouseRelativeY = mouseY - canvasCenterY
  
  // 计算缩放比例变化
  const scaleRatio = newScale / oldScale
  
  // 更新缩放比例
  mapScale.value = newScale
  
  // 调整偏移量，使鼠标位置保持不变
  mapOffset.value = {
    x: mapOffset.value.x - mouseRelativeX * (scaleRatio - 1),
    y: mapOffset.value.y - mouseRelativeY * (scaleRatio - 1)
  }
}

// 地图拖拽
const handleMapMouseDown = (event: MouseEvent) => {
  isDragging.value = true
  dragStart.value = { x: event.clientX, y: event.clientY }
  dragStartOffset.value = { ...mapOffset.value }
  event.preventDefault()
}

const handleMapMouseMove = (event: MouseEvent) => {
  if (!isDragging.value) return
  
  const deltaX = event.clientX - dragStart.value.x
  const deltaY = event.clientY - dragStart.value.y
  
  mapOffset.value = {
    x: dragStartOffset.value.x + deltaX,
    y: dragStartOffset.value.y + deltaY
  }
}

const handleMapMouseUp = () => {
  isDragging.value = false
}

const getObjectColor = (objectType: string): string | null => {
  return objectColors[objectType as keyof typeof objectColors] || null
}

onMounted(() => {
  // 可以在这里设置默认值或加载默认地图
})
</script>

<style scoped>
.room-map-layout {
  display: flex;
  height: 100vh;
  width: 100vw;
  background: #f5f7fa;
}

/* 侧边栏样式 */
.sidebar {
  background: white;
  border-right: 1px solid #e4e7ed;
  transition: all 0.3s ease;
  width: 320px;
  display: flex;
  flex-direction: column;
  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
  z-index: 100;
}

.sidebar.collapsed {
  width: 60px;
}

.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
  border-bottom: 1px solid #e4e7ed;
  background: #fafbfc;
  min-height: 60px;
}

.sidebar-title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.collapse-btn {
  margin-left: auto;
}

.controls {
  padding: 20px;
  flex: 1;
  overflow-y: auto;
}

.map-controls {
  margin-top: 20px;
}

.error-message {
  padding: 16px;
  margin-top: auto;
}

/* 地图区域样式 */
.map-area {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f7fa;
  position: relative;
  overflow: hidden;
  height: 100vh;
  width: 100%;
}

.map-container {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  padding: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}

.map-viewport {
  position: relative;
  overflow: hidden;
  border-radius: 4px;
  background: white;
  user-select: none;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.room-map {
  border: 1px solid #dcdfe6;
  background: white;
  transition: transform 0.1s ease;
  transform-origin: center center;
}

.map-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .sidebar {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    z-index: 1000;
  }
  
  .sidebar.collapsed {
    transform: translateX(-100%);
    width: 320px;
  }
  
  .map-area {
    width: 100%;
  }
}

/* Element Plus 组件样式覆盖 */
.el-form-item {
  margin-bottom: 16px;
}

.el-form-item__label {
  font-weight: 500;
  color: #606266;
}

.el-slider {
  margin: 8px 0;
}

.el-divider {
  margin: 16px 0;
}

.el-divider__text {
  font-size: 14px;
  font-weight: 500;
  color: #606266;
}
</style>
